package com.example.myopencv.roundcamera;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Region;
import android.hardware.Camera;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.WindowManager;

import java.util.List;

/**
 * 圆形摄像头预览控件
 *
 * 支持暂停预览，圆形的摄像头预览
 */
public class CircleRoundCameraPreview extends SurfaceView   {

    private static final String TAG = "CircleCameraPreview";

    /**
     * 半径
     */
    private int radius;

    /**
     * 中心点坐标
     */
    private Point centerPoint;

    /**
     * 剪切路径
     */
    private Path clipPath;

    /**
     * 是否在预览
     */
    private boolean isPreviewing;

    /**
     * 是否已经设置过窗口尺寸
     */
    private boolean isSizeFitted = false;

    /**
     * 预览回调
     */
    private Camera.PreviewCallback previewCallback;


    public CircleRoundCameraPreview(Context context) {
        super(context);
        init();
    }

    public CircleRoundCameraPreview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleRoundCameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        this.setFocusable(true);
        this.setFocusableInTouchMode(true);

        clipPath = new Path();
        centerPoint = new Point();
    }


    /**
     * 暂停预览功能
     *
     * @return true - 开启预览； false - 暂停预览
     */


    /**
     * 暂停预览功能
     *

     */

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 坐标转换为实际像素
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        // 计算出圆形的中心点
        centerPoint.x = widthSize >> 1;
        centerPoint.y = heightSize >> 1;
        // 计算出最短的边的一半作为半径
        radius = ( centerPoint.x > centerPoint.y) ? centerPoint.y : centerPoint.x;
        Log.i(TAG, "onMeasure: " + centerPoint.toString());
        clipPath.reset();
        clipPath.addCircle(centerPoint.x, centerPoint.y, radius, Path.Direction.CCW);
        setMeasuredDimension(widthSize, heightSize);
    }


    /**
     * 绘制
     *
     * @param canvas 画布
     */
    @Override
    public void draw(Canvas canvas) {
        //裁剪画布，并设置其填充方式
        if (Build.VERSION.SDK_INT >= 26) {
            canvas.clipPath(clipPath);
        } else {
            canvas.clipPath(clipPath, Region.Op.REPLACE);
        }
        super.draw(canvas);
    }

    /**
     * 根据相机旋转动态修改view的尺寸
     * <p>
     * 以抵消失真的现象
     *
     * @param rotate 旋转角度
     */
    private void changeViewSize(int rotate) {
        if (isSizeFitted) {
            // 如果屏幕尺寸已经重设过那么，则认为不需要再设置
            return;
        }
        isSizeFitted = true;

        DisplayMetrics metrics = new DisplayMetrics();
        ((WindowManager) getContext()
                .getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay().getMetrics(metrics);

        ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
        if (rotate == 0) {
            layoutParams.height = layoutParams.width * 3 / 4;
        } else {
            layoutParams.width = layoutParams.width * 3 / 4;
        }
        this.setLayoutParams(layoutParams);
    }



    /**
     * 获取最大支持 4:3 图像尺寸
     *
     * @param params 参数
     * @return 最大尺寸
     */
    private Camera.Size getMaxPictureSize(Camera.Parameters params) {
        List<Camera.Size> previewSizes = params.getSupportedPictureSizes();
        int maxArea = -1;
        Camera.Size maxSize = null;

        for (Camera.Size size : previewSizes) {
            Log.i(TAG, "Support size -> " + size.width + " x " + size.height);

            int gcd = gcd(size.width, size.height);
            int w = size.width / gcd;
            int h = size.height / gcd;
            if (w == 4 && h == 3 && (size.width * size.height) > maxArea) {
                maxArea = size.width * size.height;
                maxSize = size;
            }
        }
        Log.i(TAG, "Max 4:3 -> " + maxSize.width + " x " + maxSize.height);
        return maxSize;
    }

    /**
     * 计算最大公约数
     *
     * @param a
     * @param b
     * @return 最大公约数
     */
    private int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }
}
